using System;

namespace SmartMathLibrary
{
    /// <summary>
    /// Interface to implement a Matrix class.
    /// </summary>
    public interface IMatrix
    {
        /// <summary>
        /// Gets the number of matrix columns.
        /// </summary>
        int Columns { get; }

        /// <summary>
        /// Gets the number of matrix rows.
        /// </summary>
        int Rows { get; }

        /// <summary>
        /// Gets the matrix data in form of an array.
        /// </summary>
        double[,] MatrixData { get; }

        /// <summary>
        /// Determines whether the current matrix is a square matrix.
        /// </summary>
        /// <value>
        /// True if the current matrix is a square matrix otherwise, false. 
        /// </value>
        bool IsSquareMatrix { get; }

        /// <summary>
        /// Determines whether the current matrix is symmetric.
        /// </summary>
        /// <value>
        /// True if the current matrix is symmetric otherwise, false.
        /// </value>
        bool IsSymmetricMatrix { get; }

        /// <summary>
        /// Determines whether the current matrix is a diagonal matrix.
        /// </summary>
        /// <value>
        /// True if the current matrix is a diagonal matrix otherwise, false.
        /// </value>
        bool IsDiagonalMatrix { get; }

        /// <summary>
        /// Determines whether the current matrix is a column vector.
        /// </summary>
        /// <value>
        /// True if the current matrix is a column vector otherwise, false.
        /// </value>
        bool IsColumnVector { get; }

        /// <summary>
        /// Determines whether the current matrix is a row vector.
        /// </summary>
        /// <value>
        /// True if this instance is row vector otherwise, false.
        /// </value>
        bool IsRowVector { get; }

        /// <summary>
        /// Gets the trace of the matrix.
        /// </summary>
        /// <value>The trace of the matrix.</value>
        double Trace { get; }

        /// <summary>
        /// Creates the unit matrix of the current matrix. The new matrix will overwrite the
        /// old one.
        /// </summary>
        void CreateIdentityMatrix();

        /// <summary>
        /// Solves the linear system of the matrix by using the Gauss elimination method. 
        /// To solve the system of equation, the matrix has to be am extended coefficient matrix.
        /// The new matrix will overwrite the old one.
        /// </summary>
        /// <returns>The results of the system solve.</returns>
        Double[] SolveLinearSystem();

        /// <summary>
        /// Creates the upper triangular matrix. The new matrix will overwrite the
        /// old one.
        /// </summary>
        void CreateUpperTriangularMatrix();

        /// <summary>
        /// Creates the diagonal matrix. The new matrix will overwrite the 
        /// old one.
        /// </summary>
        void CreateDiagonalMatrix();

        /// <summary>
        /// Calculates the main diagonal product of the current matrix.
        /// </summary>
        /// <returns>The main diagonal product of the current matrix.</returns>
        double CalculateMainDiagonalProduct();

        /// <summary>
        /// Calculates the determinant of the current matrix.
        /// </summary>
        /// <returns>The determinant of the current matrix.</returns>
        double CalculateDeterminant();

        /// <summary>
        /// Creates the sign inverted matrix of the current instance.
        /// </summary>
        /// <returns>The sign inverted matrix of the current instance.</returns>
        Matrix CreateSignInvertedMatrix();

        /// <summary>
        /// Transposes the current matrix.
        /// </summary>
        /// <returns>The transposed matrix.</returns>
        Matrix Transpose();

        /// <summary>
        /// Gets the value at the specified position of the matrix.
        /// </summary>
        /// <param name="position">The specified position where the value should be set.</param>
        /// <returns>The value at the specified position.</returns>
        Double GetValueAtPosition(MatrixPosition position);

        /// <summary>
        /// Gets the value at the specified position of the matrix.
        /// </summary>
        /// <param name="row">The row index where the value should be set.</param>
        /// <param name="column">The column index where the value should be set.</param>
        /// <returns>The value at the specified position.</returns>
        Double GetValueAtPosition(int row, int column);

        /// <summary>
        /// Sets a specified value at a specified position of the matrix.
        /// </summary>
        /// <param name="position">The position where the value should be set.</param>
        /// <param name="value">The number of the element.</param>
        void SetValueAtPosition(MatrixPosition position, Double value);

        /// <summary>
        /// Sets a specified value at a specified position of the matrix.
        /// </summary>
        /// <param name="row">The row index of the new value.</param>
        /// <param name="column">The column index of the new value.</param>
        /// <param name="value">The number of the element.</param>
        void SetValueAtPosition(int row, int column, Double value);

        /// <summary>
        /// Copies the current instance.
        /// </summary>
        /// <returns>A copy of the current instance.</returns>
        Matrix Copy();

        /// <summary>
        /// Checks if the current instance of the matrix is equals
        /// to another.
        /// </summary>
        /// <param name="matrix">The matrix to compare.</param>
        /// <returns>Returns true if the matrix is even to the specified compare matrix else the method returns false.</returns>
        bool CompareTo(Matrix matrix);
    }
}